package com.xiaoma.thread.wait;

import java.util.Queue;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;

public class Main {
  public static void main(String[] args) {
    Main main = new Main();
    new Thread(main::producer, "producer thread").start();
    new Thread(main::consumer, "consumer thread").start();
    System.out.println("主线程执行到最后一行！");
  }

  //----------------------------------------
  private static final Queue<String> stringList = new LinkedBlockingQueue<>();

  /*
   以stringList为monitor，一次往其中添加一条信息，直到加到五条，然后将所锁对象让给消费者
   */
  public void producer() {
    while (true) {
      System.out.println("生产者 进入 while 循环第一行");
      synchronized (stringList) {

        while (stringList.size() < 5) {
          String l = System.currentTimeMillis()+""+new Random().nextInt();
          System.out.println(Thread.currentThread().getName() + " : " + "producer will add: " +l);
          stringList.add(l);

        }

        try {
          stringList.wait();//加满了，让出monitor，自身处于blocking状态
        } catch (InterruptedException e) {
          e.printStackTrace();
        }

        stringList.notifyAll();//通知其他以stringList为锁的同步块，可以竞争锁资源了
        System.out.println("生产者 同步块 最后一行");
      }

      System.out.println("生产者 while循环 最后一行");
    }
  }

  /*
  消费者，取得锁之后就去消费，打印相应的值并且将值删除
   */
  public void consumer() {
    while (true) {
      System.out.println("消费者 进入 while 循环第一行");
      synchronized (stringList) {

        while (!stringList.isEmpty()) {
          System.out.println(Thread.currentThread().getName() + " : " + "consumer will remove: " + stringList.peek());
          stringList.remove();
        }

        try {
          stringList.wait();//全部消费完毕，让monitor资源
        } catch (InterruptedException e) {
          e.printStackTrace();
        }

        stringList.notifyAll();//通知其他的线程可以竞争monitor资源了

        System.out.println("消费者 同步块 最后一行");
      }

      System.out.println("生产者 while循环 最后一行");
    }
  }

    /*
    wait和notify必须在同步块中，并且，必须通过被monitor的对象进行调用！
     */
}
